package cn.broadsense.biz.service.impl;

import cn.broadsense.biz.convert.ChannelConvert;
import cn.broadsense.biz.domain.Channel;
import cn.broadsense.biz.domain.ChannelTag;
import cn.broadsense.biz.domain.ChannelTagDetails;
import cn.broadsense.biz.domain.TagRule;
import cn.broadsense.biz.dto.ChannelTagTreeDto;
import cn.broadsense.biz.mapper.ChannelTagMapper;
import cn.broadsense.biz.service.ChannelService;
import cn.broadsense.biz.service.ChannelTagDetailsService;
import cn.broadsense.biz.service.ChannelTagService;
import cn.broadsense.biz.service.TagRuleService;
import cn.broadsense.biz.utils.IdGenerationUtil;
import cn.broadsense.biz.vo.ChannelTagVo;
import cn.broadsense.common.exception.ServiceException;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author bs
 * @description 针对表【t_channel_tag(点位标签)】的数据库操作Service实现
 * @createDate 2023-09-25 16:21:44
 */
@Service
public class ChannelTagServiceImpl extends ServiceImpl<ChannelTagMapper, ChannelTag>
        implements ChannelTagService {

    @Resource
    private ChannelConvert channelConvert;

    @Resource
    private ChannelService channelService;

    @Resource
    private ChannelTagDetailsService tagDetailsService;

    @Resource
    private ChannelTagMapper channelTagMapper;

    @Resource
    private TagRuleService tagRuleService;

    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    public List<ChannelTagTreeDto> tagTree(Boolean isFilter) {
        List<ChannelTag> list = list();
        if (CollUtil.isNotEmpty(list) && (isFilter != null && isFilter)) {
            list = list.stream().filter(e -> e.getChannelQty() != null && e.getChannelQty() > 0).collect(Collectors.toList());
        }
        return buildTree(list);
    }

    @Override
    public void insertTag(ChannelTagVo channelTagVo) {
        String parentCode = channelTagVo.getParentCode();
        LambdaQueryWrapper<ChannelTag> query2 = new LambdaQueryWrapper<>();
        query2.eq(ChannelTag::getName, channelTagVo.getName());
        query2.last("limit 1");
        ChannelTag channelTag2 = this.baseMapper.selectOne(query2);
        if (channelTag2 != null) {
            throw new ServiceException("视频标签" + channelTagVo.getName() + "已存在");
        }
        String fullCode = "";
        if (StrUtil.isBlank(channelTagVo.getParentCode())) {
            parentCode = "0";
            fullCode = "0";
        } else {
            LambdaQueryWrapper<ChannelTag> query = new LambdaQueryWrapper<>();
            query.eq(ChannelTag::getCode, parentCode);
            ChannelTag channelTag = this.baseMapper.selectOne(query);
            if (channelTag == null) {
                throw new ServiceException("父类编码不存在，请核实");
            }
            if (!"0".equals(channelTag.getParentCode())) {
                throw new ServiceException("最多只能添加二级标签");
            }
            fullCode = channelTag.getFullCode();

        }
        String code = channelTagVo.getCode();
        fullCode = fullCode + "," + code;

        if (StrUtil.isBlank(channelTagVo.getCode())) {
            code = IdGenerationUtil.tagCode();
        }
        ChannelTag channelTag = new ChannelTag();
        channelTag.setCode(code);
        channelTag.setTagRuleId(channelTagVo.getTagRuleId());
        channelTag.setTagRuleName(channelTagVo.getTagRuleName());
        channelTag.setName(channelTagVo.getName());
        channelTag.setCreateTime(new Date());
        channelTag.setParentCode(parentCode);
        channelTag.setTagType(channelTagVo.getTagType());
        channelTag.setFullCode(fullCode);
        this.baseMapper.insert(channelTag);
    }

    @Override
    public void delete(Long id) {
        ChannelTag tag = getById(id);
        if (tag == null) {
            throw new ServiceException("标签不存在");
        }
        LambdaQueryWrapper<ChannelTag> query = new LambdaQueryWrapper<>();
        query.eq(ChannelTag::getParentCode, tag.getCode());
        List<ChannelTag> channelTags = this.baseMapper.selectList(query);
        if (CollUtil.isNotEmpty(channelTags)) {
            throw new ServiceException("当前标签存在子节点，无法删除");
        }
        this.baseMapper.deleteById(id);
    }

    @Override
    public void edit(Long id, ChannelTagVo tagVo) {
        ChannelTag tag = getById(id);
        if (tag == null) {
            throw new ServiceException("标签不存在");
        }
        if (StrUtil.isBlank(tagVo.getName())) {
            throw new ServiceException("标签名称不能为空");
        }
        if (StrUtil.isBlank(tagVo.getTagType())) {
            throw new ServiceException("标签类型不能为空");
        }
        LambdaUpdateWrapper<ChannelTag> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(ChannelTag::getName, tagVo.getName());
        updateWrapper.set(ChannelTag::getTagType, tagVo.getTagType());
        updateWrapper.set(tagVo.getTagRuleId() != null, ChannelTag::getTagRuleId, tagVo.getTagRuleId());
        updateWrapper.set(StrUtil.isNotBlank(tagVo.getTagRuleName()), ChannelTag::getTagRuleName, tagVo.getTagRuleName());
        updateWrapper.eq(ChannelTag::getId, id);
        this.update(updateWrapper);
    }


    @Override
    public List<ChannelTagTreeDto> mapTagTree() {
        List<ChannelTagTreeDto> resultList = new ArrayList<>();

        LambdaQueryWrapper<ChannelTag> query = new LambdaQueryWrapper<>();
        query.isNotNull(ChannelTag::getTagRuleId);
        query.eq(ChannelTag::getParentCode, "0");
        List<ChannelTag> list = this.list(query);
        if (CollUtil.isEmpty(list)) {
            return resultList;

        }
        List<TagRule> tagRules = tagRuleService.listByIds(list.stream().map(ChannelTag::getTagRuleId).collect(Collectors.toSet()));
        if (CollUtil.isEmpty(tagRules)) {
            return resultList;
        }
        List<TagRule> showTagRule = tagRules.stream().filter(e -> e.getShowMap() == 1).collect(Collectors.toList());
        if (CollUtil.isEmpty(showTagRule)) {
            return resultList;
        }
        Map<Long, String> showTagRuleMap = showTagRule.stream().collect(Collectors.toMap(TagRule::getId, TagRule::getRuleName));
        list = list.stream().filter(e -> showTagRuleMap.containsKey(e.getTagRuleId())).collect(Collectors.toList());
        if (CollUtil.isEmpty(list)) {
            return resultList;
        }
        //查询子类
        LambdaQueryWrapper<ChannelTag> query2 = new LambdaQueryWrapper<>();
        query2.in(ChannelTag::getParentCode, list.stream().map(ChannelTag::getCode).collect(Collectors.toList()));
        List<ChannelTag> list2 = this.list(query2);
        list.addAll(list2);
        resultList = buildTree(list);
        return resultList;
    }

    @Override
    public List<ChannelTagTreeDto> contentTreeTag() {
        LambdaQueryWrapper<ChannelTag> query = new LambdaQueryWrapper<>();
        query.eq(ChannelTag::getParentCode, "0");
        List<ChannelTag> parentList = this.list(query);
        List<Long> tagIds = tagDetailsService.channelTagId();
        if (CollUtil.isNotEmpty(tagIds)) {
            LambdaQueryWrapper<ChannelTag> query2 = new LambdaQueryWrapper<>();
            query2.ne(ChannelTag::getParentCode, "0");
            query2.in(ChannelTag::getId, tagIds);
            List<ChannelTag> tagList = this.list(query2);
            CollUtil.addAll(parentList, tagList);
        }
        return buildTree(parentList);
    }

    @Override
    public List<ChannelTag> listByChannelIds(List<Long> channelIds) {

        return this.baseMapper.listByChannelIds(channelIds);
    }

    @Override
    public void relationChannel(Long tagId, List<Long> channelIds) {
        ChannelTag channelTag = super.getById(tagId);
        if (channelTag == null) {
            throw new ServiceException("标签不存在");
        }

        if (CollUtil.isEmpty(channelIds)) {
            throw new ServiceException("点位列表不能为空");
        }
        if ("0".equals(channelTag.getParentCode())) {
            throw new ServiceException("只能关联子标签");
        }

        LambdaQueryWrapper<ChannelTagDetails> query = new LambdaQueryWrapper<>();
        query.eq(ChannelTagDetails::getTagId, tagId);
        query.select(ChannelTagDetails::getChannelId);
        List<ChannelTagDetails> list = tagDetailsService.list(query);
        Collection<Long> disjunction = channelIds;
        if (CollUtil.isNotEmpty(list)) {
            List<Long> collect = list.stream().map(ChannelTagDetails::getChannelId).collect(Collectors.toList());
            disjunction = CollUtil.subtract(channelIds, collect);
        }

        if (CollUtil.isEmpty(disjunction)) {
            throw new ServiceException("当前点位已关联该标签");
        }
        List<Channel> channelList = channelService.listByIds(disjunction);
        if (CollUtil.isEmpty(channelList)) {
            throw new ServiceException("当前点位已关联该标签");
        }
        Date date = new Date();
        List<ChannelTagDetails> tagList = new ArrayList<>();
        for (Channel channel : channelList) {
            ChannelTagDetails tagDetails = new ChannelTagDetails();
            tagDetails.setTagId(tagId);
            tagDetails.setChannelId(channel.getId());
            tagDetails.setCreateTime(date);
            tagList.add(tagDetails);
        }

        tagDetailsService.saveBatch(tagList);

        syncChannelQty();
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void relationChannelV2(Long channelId, List<Long> tagIds) {
        Channel channel = channelService.getById(channelId);
        if (null == channel) {
            throw new ServiceException("点位不存在");
        }
        List<ChannelTag> channelTags = listByIds(tagIds);
        if (CollUtil.isEmpty(channelTags)) {
            throw new ServiceException("标签列表不存在");
        }
        Set<Long> tagIdSets = new HashSet<>();
        for (ChannelTag channelTag : channelTags) {
            if ("0".equals(channelTag.getParentCode())) {
                throw new ServiceException("只能关联子标签");
            }
            tagIdSets.add(channelTag.getId());
        }
        List<ChannelTagDetails> detailsList = tagDetailsService.listByChannelId(channelId);
        Map<Long, Long> idMap = new HashMap<>();
        if (CollUtil.isNotEmpty(detailsList)) {
            detailsList.forEach(e -> {
                idMap.put(e.getTagId(), e.getId());
                tagIdSets.remove(e.getTagId());
            });
        }
        //比对删除的
        Collection<Long> removeList = CollUtil.subtract(idMap.keySet(), tagIds);
        if (CollUtil.isNotEmpty(removeList)) {
            List<Long> removeIds = new ArrayList<>();
            removeList.forEach(e -> removeIds.add(idMap.get(e)));
            tagDetailsService.removeBatchByIds(removeIds);
        }

        Date date = new Date();
        List<ChannelTagDetails> tagList = new ArrayList<>();
        for (Long tagId : tagIdSets) {
            ChannelTagDetails tagDetails = new ChannelTagDetails();
            tagDetails.setTagId(tagId);
            tagDetails.setChannelId(channelId);
            tagDetails.setCreateTime(date);
            tagList.add(tagDetails);
        }
        tagDetailsService.saveBatch(tagList);
        syncChannelQty();
    }

    private void syncChannelQty() {
        threadPoolTaskExecutor.execute(() -> {
            //更新点位标签数量
            List<ChannelTag> channelTagList = this.baseMapper.countQtyList();
            if (CollUtil.isNotEmpty(channelTagList)) {
                this.baseMapper.updateChannelQty(channelTagList);
            }
            this.baseMapper.updateChannelQty2();
            //更新填写3d数据的标签数量
            List<ChannelTag> channelTagList1 = this.baseMapper.countThirdQtyList();
            if (CollUtil.isNotEmpty(channelTagList1)) {
                this.baseMapper.updateChannelThirdQty(channelTagList1);
            }

            this.baseMapper.updateChannelThirdQty2();
            List<ChannelTag> channelTagList2 = this.baseMapper.countPQtyList();
            //更新父类的标签数量
            if (CollUtil.isNotEmpty(channelTagList2)) {
                this.baseMapper.updateChannelParentQty(channelTagList2);
            }


        });
    }


    private List<ChannelTagTreeDto> buildTree(List<ChannelTag> list) {
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        Map<String, List<ChannelTag>> parentMap = list.stream().collect(Collectors.groupingBy(ChannelTag::getParentCode));
        //获取跟节点
        List<ChannelTag> channelTags = parentMap.get("0");
        if (CollUtil.isEmpty(channelTags)) {
            return new ArrayList<>();
        }
        List<ChannelTagTreeDto> tagTreeDtoList = channelConvert.toChannelTagTreeList(channelTags);
        buildChildren(tagTreeDtoList, parentMap);
        return tagTreeDtoList;
    }

    private List<ChannelTagTreeDto> buildChildren(List<ChannelTagTreeDto> treeDtoList, Map<String, List<ChannelTag>> parentMap) {
        if (CollUtil.isNotEmpty(treeDtoList)) {
            for (ChannelTagTreeDto dto : treeDtoList) {
                String code = dto.getCode();
                List<ChannelTag> channelTagList = parentMap.get(code);
                if (CollUtil.isNotEmpty(channelTagList)) {
                    List<ChannelTagTreeDto> treeDtos = channelConvert.toChannelTagTreeList(channelTagList);
                    List<ChannelTagTreeDto> treeList = buildChildren(treeDtos, parentMap);
                    dto.setChildrenList(treeList);
                }
            }
        }
        return treeDtoList;
    }
}




